package xyz.thoughtset.viewer.executor.blocks.executor;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import xyz.thoughtset.viewer.common.exc.exceptions.ExecException;
import xyz.thoughtset.viewer.executor.blocks.constants.NodeConstant;
import xyz.thoughtset.viewer.modules.step.entity.IteratorBody;
import xyz.thoughtset.viewer.modules.step.entity.block.BlockBodyEle;
import xyz.thoughtset.viewer.modules.step.entity.block.BlockInfo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.LongAdder;

//todo
@Component
public class IteratorBlockExecutor extends AbstractBlockExecutor<IteratorBody>  {


    @Override
    protected Object doQuery(BlockInfo block, IteratorBody body, Map<String, Object> params, ExpressionParser parser, StandardEvaluationContext context) throws ExecException {
        List<Object> results = new ArrayList<>();
        LongAdder index = new LongAdder();
        context.setVariable(NodeConstant.DATA_NODE, results);
        params.put(NodeConstant.DATA_NODE, results);
        Collection dataList = dataList(body, params, parser, context);
        if (!ObjectUtils.isEmpty(dataList)) {
            for (Object data : dataList) {
                context.setVariable(NodeConstant.CURRENT_DATA_NODE_INDEX, index.intValue());
                params.put(NodeConstant.CURRENT_DATA_NODE_INDEX, index.intValue());
                params.put(NodeConstant.CURRENT_DATA, data);
                context.setVariable(NodeConstant.CURRENT_DATA, data);
                doLoop(results, body, params, parser, context, index);
            }
        }
        params.remove(NodeConstant.DATA_NODE);
        context.setVariable(NodeConstant.DATA_NODE,null);
        context.setVariable(NodeConstant.CURRENT_DATA_NODE_INDEX, null);
        params.remove(NodeConstant.CURRENT_DATA_NODE_INDEX);
        context.setVariable(NodeConstant.CURRENT_DATA, null);
        params.remove(NodeConstant.CURRENT_DATA);
        return results;
    }

    protected void doLoop(List<Object> results, IteratorBody body, Map<String, Object> params, ExpressionParser parser, StandardEvaluationContext context, LongAdder index) {
        List eleResults = new ArrayList<>(body.getBodyEles().size()+1);
        results.add(eleResults);
        for (BlockBodyEle ele : body.getBodyEles()) {
            eleResults.add(execNode(ele, params, parser, context));
        }
        index.increment();
    }

    protected Collection dataList(IteratorBody body, Map<String, Object> params, ExpressionParser parser, StandardEvaluationContext context) {
        String condition = body.getIteratorRepx();
        if (condition != null && !condition.isEmpty()) {
            Object result = parser.parseExpression(condition.startsWith("#")?condition:"#"+condition).getValue(context);
            if(!ObjectUtils.isEmpty(result)) {
                if (result instanceof Map) {
                    return ((Map<?, ?>) result).entrySet();
                } else if (result instanceof Collection) {
                    return (Collection) result;
                } else {
                    return List.of(result);
                }
            }
        }
        return null;
    }


}
